#ifndef RSUCONNECT
#define RSUCONNECT

#include <QObject>
#include <QTcpSocket>

class RsuConnect : public QObject
{
    Q_OBJECT

public:
    explicit RsuConnect(QObject *parent = 0);
    ~RsuConnect();

//public:
//    void openRsu(const QString &host, quint16 port);
//    void closeRsu();

//protected slots:
//    void tryReconnect();

public:
    /*!
    * \brief 命令执行成功
    */
    const static int ERR_SUCCESS = 0;

    /*!
     * \brief 超时，RSU设备无响应
     */
    const static int ERR_RSU_OVERTIME = -100;

    /*!
     * \brief 传入参数错误
     */
    const static int ERR_RSU_API_INPUT_ERROR = -1000;

    /*!
     * \brief 设备未打开
     */
    const static int ERR_RSU_NOT_OPENED = -1001;

    /*!
     * \brief 其他错误
     */
    const static int ERR_RSU_OTHER = -2000;

public:
    int initRsuRq(char *Time, int BSTInterval, int TxPower, int PLLChannelID);
    int initPrimRq(char *BeaconID, char *Time, int Profile, int MandApplicationlist,
                   char *MandApplication, int Profilelist);
    int rsuInfoRq();

    // 发送原语指令,释放OBU
    int reportEventRq(int Mode, int DID, int EventType);

protected:
    static quint8 getXOR(const QByteArray &data);
    bool processDataRead(const QByteArray &dataRead, QByteArray *pExpectedFrame, quint8 nExpectedFrameType);
    bool processRawFrame(QByteArray &frame, QByteArray *pExpectedFrame, quint8 nExpectedFrameType);
    void processFrame(quint8 nFrameIndex, quint8 nFrameType, QByteArray &frame);

    /*!
     * \brief 封装帧数据，进行转义并增加帧头、帧序号、校验码、帧尾。
     * \param 待封装数据。
     */
    void wrapFrame(QByteArray &data);

    /*!
     * \brief 封装并发送帧数据。
     * \param date: 待发送数据
     * \return
     */
    int wrapAndSendFrame(QByteArray &data);

protected:
    QTcpSocket m_tcpSocket;
    /*!
     * \brief m_dataRead: 已都到原始数据。
     */
    QByteArray m_dataRead;

    /*!
     * \brief m_sHostAddr: 天线IP地址。
     */
    QString m_sHostAddr;

    /*!
     * \brief m_nHostPort: 天线监听端口。
     */
    quint16 m_nHostPort;

    /*!
     * \brief m_bReadInBlockMode:
     * 是否处于阻塞式读取状态，在这一状态，readReady事件中不读数据。
     * 该数值在发送请求后,需要立刻读取返回值时需要,在只读OBU不涉及交易的情况下
     * 该参数无效
     */
    //    bool m_bReadInBlockMode;

protected:
    // 在发射bst命令时用到
    static int getCmdGroupLen(int cmdCount, const char *cmdGroup)
    {
        int n=0;
        for (int i=0; i<cmdCount; i++)
        {
            n+=(cmdGroup[n]+1);
        }
        return n;
    }

    quint8 getRSCTL();
    quint8 m_frameIndex;

signals:
    void newFrameArrived(quint8 nFrameIndex, quint8 nFrameType, const QByteArray &frame);
    void stateChanged(QAbstractSocket::SocketState);

protected slots:
    void socketConnected();
    void socketDisconnected();
    void socketBytesWritten(qint64 bytes);
    void socketReadyRead();
    void socketStateChanged(QAbstractSocket::SocketState socketState);
    void socketError(QAbstractSocket::SocketError socketError);
};

#endif // RSUCONNECT

